﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Liang.Device
{
    /// <summary>
    /// 串口数据接收事件DataReceivedHandler
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void ReceiveDataHandler(object sender, ReceiveDataArgs e);

    public class ComPort
    {
        /// <summary>
        /// 串口是否已打开
        /// </summary>
        bool isOpened = false;

        public bool IsOpened
        {
            get { return isOpened; }
        }

        private SerialPort serialPort = null;

        /// <summary>
        /// 数据同步对象
        /// </summary>
        object m_synDataObject = new object();

        /// <summary>
        /// 串口构造函数
        /// </summary>
        /// <param name="strPort">串口</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="parity">校验位</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="stopBits">停止位</param>
        public ComPort(string strPort, int baudRate, Parity parity, int dataBits, StopBits stopBits)
        {
            try
            {
                serialPort = new SerialPort(strPort, baudRate, parity, dataBits, stopBits);
                serialPort.DtrEnable = true;
                serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
            }
            catch (System.IO.IOException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 参数格式：COM1,9600,n,8,1
        /// <para>不区分大小写</para>
        /// </summary>
        /// <param name="strPortConfig"></param>
        public ComPort(string strPortConfig)
        {
            try
            {
                string[] config = strPortConfig.Split(',');
                string portName = config[0];
                int baudRate = int.Parse(config[1]);
                Parity parity = Parity.None;
                if (string.Equals("Odd", config[2], StringComparison.CurrentCultureIgnoreCase))
                {
                    parity = Parity.Odd;
                }
                else if (string.Equals("Even", config[2], StringComparison.CurrentCultureIgnoreCase))
                {
                    parity = Parity.Even;
                }
                else if (string.Equals("Mark", config[2], StringComparison.CurrentCultureIgnoreCase))
                {
                    parity = Parity.Mark;
                }
                else if (string.Equals("Space", config[2], StringComparison.CurrentCultureIgnoreCase))
                {
                    parity = Parity.Space;
                }
                else
                {
                    parity = Parity.None;
                }
                int dataBits = int.Parse(config[3]);
                StopBits stopBits = (StopBits)int.Parse(config[4]);

                serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
                serialPort.DtrEnable = true;
                serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
            }
            catch
            {
                throw new Exception("无效的串口配置参数");
            }
        }

        /// <summary>
        /// 打开串口
        /// </summary>
        /// <returns></returns>
        public bool Open()
        {
            if (isOpened)
            {
                return true;
            }

            try
            {
                serialPort.Open();
                isOpened = true;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }

            return true;
        }

        /// <summary>
        /// 关闭串口
        /// </summary>
        /// <returns></returns>
        public bool Close()
        {
            if (!isOpened)
            {
                return true;
            }

            try
            {
                serialPort.Close();
                isOpened = false;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }

            return true;
        }

        public void SendData(string strData)
        {
            if (null != serialPort)
            {
                serialPort.Write(strData);
            }
        }

        public void SendData(byte[] data)
        {
            if (null != serialPort)
            {
                serialPort.Write(data, 0, data.Length);
            }
        }

        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                SerialPort sp = (SerialPort)sender;

                // 处理数据
                int nBytesToRead = sp.BytesToRead;
                byte[] tmp = new byte[nBytesToRead];
                sp.Read(tmp, 0, nBytesToRead);
                ReceiveDataArgs my_e = new ReceiveDataArgs(tmp);

                OnReceviceData(my_e);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        // 声明事件
        public event ReceiveDataHandler ReceivedDataEvent;

        // 事件处理函数
        protected virtual void OnReceviceData(ReceiveDataArgs e)
        {
            if (null != ReceivedDataEvent)
            {
                ReceivedDataEvent(this, e);
            }
        }
    }

    public class ReceiveDataArgs : EventArgs
    {
        public readonly byte[] ReceivedData;

        public ReceiveDataArgs(byte[] Data)
        {
            ReceivedData = Data;
        }
    }
}
